﻿using System;
using ZyGame.Execute;
using ZyGame.Resource;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

namespace ZyGame.UI
{
    public static class UIExtension
    {
        public static T GetComponent<T>(this UIWindow window, string name) where T : Component
        {
            if (window is null || window.gameObject is null)
            {
                return default;
            }

            GameObject gameObject = window.GetChild(name);
            if (gameObject is null)
            {
                return default;
            }

            return gameObject.GetComponent<T>();
        }

        public static T GetOrAddComponent<T>(this UIWindow window, string name) where T : Component
        {
            T component = window.GetComponent<T>(name);
            if (component is null)
            {
                GameObject gameObject = window.GetChild(name);
                if (gameObject is null)
                {
                    return default;
                }

                component = gameObject.AddComponent<T>();
            }

            return component;
        }

        public static T AddComponent<T>(this UIWindow window, string name) where T : Component
        {
            return window.GetOrAddComponent<T>(name);
        }

        /// <summary>
        /// 设置点击事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnClick(this UIWindow view, string name, UnityAction action, string clickSoundPath = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            void OnClickCallback()
            {
                if (clickSoundPath.IsNullOrEmpty() is false)
                {
                    Client.Music.PlayOneShortEffectSound(clickSoundPath);
                }

                try
                {
                    action();
                }
                catch (Exception e)
                {
                    Client.Console.WriteError(e);
                }
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject is null)
            {
                return view;
            }

            Button btn = gameObject.GetComponent<Button>();
            if (btn)
            {
                btn.onClick.RemoveAllListeners();
                btn.onClick.AddListener(OnClickCallback);
            }

            return view;
        }

        /// <summary>
        /// 设置点击事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnClick(this UIWindow view, string name, UnityAction<object> action, object args, string clickSoundPath = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            return view.OnClick<object>(name, action, args, clickSoundPath);
        }

        /// <summary>
        /// 设置点击事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnClick<T>(this UIWindow view, string name, UnityAction<T> action, T args, string clickSoundPath = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            return view.OnClick(name, () => action(args), clickSoundPath);
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnSliderValueChange(this UIWindow view, string name, UnityAction<object> action, float value = 0)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            Slider slider = gameObject.GetComponent<Slider>();
            if (slider)
            {
                slider.onValueChanged.RemoveAllListeners();
                slider.onValueChanged.AddListener(new UnityAction<float>(args => action(args)));
                slider.SetValueWithoutNotify(value);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnInputFieldValueChange(this UIWindow view, string name, UnityAction<string> action, string defaultvalue = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            TMP_InputField tMP_InputField = gameObject.GetComponent<TMP_InputField>();
            if (tMP_InputField)
            {
                tMP_InputField.onValueChanged.RemoveAllListeners();
                tMP_InputField.onValueChanged.AddListener(args => action(args));
                tMP_InputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            InputField inputField = gameObject.GetComponent<InputField>();
            if (inputField)
            {
                inputField.onValueChanged.RemoveAllListeners();
                inputField.onValueChanged.AddListener(args => action(args));
                inputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnInputFieldSubmit(this UIWindow view, string name, UnityAction<string> action, string defaultvalue = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            TMP_InputField tMP_InputField = gameObject.GetComponent<TMP_InputField>();
            if (tMP_InputField)
            {
                tMP_InputField.onSubmit.RemoveAllListeners();
                tMP_InputField.onSubmit.AddListener(args => action(args));
                tMP_InputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            InputField inputField = gameObject.GetComponent<InputField>();
            if (inputField)
            {
                inputField.onSubmit.RemoveAllListeners();
                inputField.onSubmit.AddListener(args => action(args));
                inputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnInputFieldEndEdit(this UIWindow view, string name, UnityAction<string> action, string defaultvalue = "")
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            TMP_InputField tMP_InputField = gameObject.GetComponent<TMP_InputField>();
            if (tMP_InputField)
            {
                tMP_InputField.onEndEdit.RemoveAllListeners();
                tMP_InputField.onEndEdit.AddListener(args => action(args));
                tMP_InputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            InputField inputField = gameObject.GetComponent<InputField>();
            if (inputField)
            {
                inputField.onEndEdit.RemoveAllListeners();
                inputField.onEndEdit.AddListener(args => action(args));
                inputField.SetTextWithoutNotify(defaultvalue);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnDropdownValueChange(this UIWindow view, string name, UnityAction<object> action, int value = 0)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            TMP_Dropdown tMP_Dropdown = gameObject.GetComponent<TMP_Dropdown>();
            if (tMP_Dropdown)
            {
                tMP_Dropdown.onValueChanged.RemoveAllListeners();
                tMP_Dropdown.onValueChanged.AddListener(args => action(args));
                tMP_Dropdown.SetValueWithoutNotify(value);
                return view;
            }

            Dropdown dropdown = gameObject.GetComponent<Dropdown>();
            if (dropdown)
            {
                dropdown.onValueChanged.RemoveAllListeners();
                dropdown.onValueChanged.AddListener(args => action(args));
                dropdown.SetValueWithoutNotify(value);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置值改变事件
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static UIWindow OnToggleValueChange(this UIWindow view, string name, UnityAction<bool> action, bool value = false)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            Toggle toggle = gameObject.GetComponent<Toggle>();
            if (toggle)
            {
                toggle.onValueChanged.RemoveAllListeners();
                toggle.onValueChanged.AddListener(args => action(args));
                toggle.SetIsOnWithoutNotify(value);
                return view;
            }

            return view;
        }

        /// <summary>
        /// 设置文本
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static UIWindow SetText(this UIWindow view, string name, object value)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            TMP_Text tMP_Text = gameObject.GetComponent<TMP_Text>();
            if (tMP_Text)
            {
                tMP_Text.text = value.ToString();
                return view;
            }

            Text text = gameObject.GetComponent<Text>();
            if (text)
            {
                text.text = value.ToString();
            }

            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="sprite"></param>
        /// <returns></returns>
        public static UIWindow SetSprite(this UIWindow view, string name, Sprite sprite)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            Image img = gameObject.GetComponent<Image>();
            if (img == null)
            {
                return view;
            }

            img.sprite = sprite;
            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="texture"></param>
        /// <returns></returns>
        public static UIWindow SetTexture2D(this UIWindow view, string name, Texture2D texture)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            RawImage img = gameObject.GetComponent<RawImage>();
            if (img == null)
            {
                return view;
            }

            img.texture = texture;
            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="sprite"></param>
        /// <returns></returns>
        public static UIWindow SetSprite(this UIWindow view, string name, string sprite)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            gameObject.SetSprite(sprite);
            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="texture"></param>
        /// <returns></returns>
        public static UIWindow SetTexture2D(this UIWindow view, string name, string texture)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            gameObject.SetTexture2D(texture);
            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="sprite"></param>
        /// <returns></returns>
        public static UIWindow SetSpriteAsync(this UIWindow view, string name, string sprite)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            gameObject.SetSpriteAsync(sprite);
            return view;
        }

        /// <summary>
        /// 设置图片
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="texture"></param>
        /// <returns></returns>
        public static UIWindow SetTexture2DAsync(this UIWindow view, string name, string texture)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject == null)
            {
                return view;
            }

            gameObject.SetTexture2DAsync(texture);
            return view;
        }

        /// <summary>
        /// 设置列表
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="tempName"></param>
        /// <returns></returns>
        public static UIListView GetOrAddListView(this UIWindow view, string name, string tempName)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            return view.GetOrAddListView(name, tempName);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static UIListView GetListView(this UIWindow view, string name)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            return view.GetListView(name);
        }

        /// <summary>
        /// 移除列表
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static UIWindow RemoveListView(this UIWindow view, string name)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            return view.RemoveListView(name);
        }

        public static UIWindow ToLayer(this UIWindow view, int layer)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            UILayer.To(view, layer);
            return view;
        }

        public static UIWindow Activated(this UIWindow view, string name)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject != null)
            {
                gameObject.SetActive(true);
            }

            return view;
        }

        public static UIWindow Deactivated(this UIWindow view, string name)
        {
            if (view is null)
            {
                throw new System.ArgumentNullException(nameof(view));
            }

            GameObject gameObject = view.GetChild(name);
            if (gameObject != null)
            {
                gameObject.SetActive(false);
            }

            return view;
        }
    }
}